package net.risesoft.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import net.risesoft.Y9FlowableHolder;
import net.risesoft.api.platform.org.OrgUnitApi;
import net.risesoft.api.processadmin.RepositoryApi;
import net.risesoft.consts.ItemConsts;
import net.risesoft.consts.processadmin.SysVariables;
import net.risesoft.entity.DraftEntity;
import net.risesoft.entity.Item;
import net.risesoft.entity.ProcessParam;
import net.risesoft.enums.ItemBoxTypeEnum;
import net.risesoft.enums.ItemLeaveTypeEnum;
import net.risesoft.id.IdType;
import net.risesoft.id.Y9IdGenerator;
import net.risesoft.model.itemadmin.OpenDataModel;
import net.risesoft.model.platform.org.OrgUnit;
import net.risesoft.repository.jpa.DraftEntityRepository;
import net.risesoft.service.DraftEntityService;
import net.risesoft.service.attachment.AttachmentService;
import net.risesoft.service.config.ItemStartNodeRoleService;
import net.risesoft.service.core.DocumentService;
import net.risesoft.service.core.ItemService;
import net.risesoft.service.core.ProcessParamService;
import net.risesoft.service.form.FormDataService;
import net.risesoft.service.word.Y9WordService;
import net.risesoft.y9.Y9LoginUserHolder;

import jodd.util.StringUtil;

/**
 * @author qinman
 * @author zhangchongjie
 * @date 2022/12/20
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(value = "rsTenantTransactionManager", readOnly = true)
public class DraftEntityServiceImpl implements DraftEntityService {

    private final DraftEntityRepository draftEntityRepository;

    private final ItemService itemService;

    private final DocumentService documentService;

    private final RepositoryApi repositoryApi;

    private final ProcessParamService processParamService;

    private final AttachmentService attachmentService;

    private final Y9WordService y9WordService;

    private final ItemStartNodeRoleService itemStartNodeRoleService;

    private final OrgUnitApi orgUnitApi;

    private final FormDataService formDataService;

    @Transactional
    @Override
    public void deleteByProcessSerialNumber(String processSerialNumber) {
        DraftEntity draftEntity = draftEntityRepository.findByProcessSerialNumber(processSerialNumber);
        if (null != draftEntity) {
            draftEntityRepository.deleteById(draftEntity.getId());
        }
    }

    @Transactional
    @Override
    public void deleteDraft(String ids) {
        if (StringUtils.isNotBlank(ids)) {
            String[] id = ids.split(SysVariables.COMMA);
            for (String idTemp : id) {
                DraftEntity draftEntity = draftEntityRepository.findById(idTemp).orElse(null);
                assert draftEntity != null;
                String processSerialNumber = draftEntity.getProcessSerialNumber();
                draftEntityRepository.delete(draftEntity);
                try {
                    processParamService.deleteByProcessSerialNumber(processSerialNumber);
                    List<String> list = new ArrayList<>();
                    list.add(processSerialNumber);
                    attachmentService.delBatchByProcessSerialNumbers(list);
                    y9WordService.delBatchByProcessSerialNumbers(list);
                } catch (Exception e) {
                    LOGGER.error("删除流程参数失败", e);
                }
            }
        }
    }

    @Override
    @Transactional
    public OpenDataModel openDraft(String processSerialNumber, String itemId, boolean mobile) {
        String tenantId = Y9LoginUserHolder.getTenantId(), orgUnitId = Y9FlowableHolder.getOrgUnitId();
        OpenDataModel model = new OpenDataModel();
        Item item = itemService.findById(itemId);
        model.setItemId(itemId);
        model.setProcessDefinitionKey(item.getWorkflowGuid());
        String processDefinitionKey = item.getWorkflowGuid();
        String processDefinitionId =
            repositoryApi.getLatestProcessDefinitionByKey(tenantId, processDefinitionKey).getData().getId();
        String taskDefKey = itemStartNodeRoleService.getStartTaskDefKey(itemId);
        DraftEntity draft = draftEntityRepository.findByProcessSerialNumber(processSerialNumber);
        ProcessParam processParam = processParamService.findByProcessSerialNumber(processSerialNumber);
        model.setCustomItem(processParam.getCustomItem());
        model.setProcessDefinitionId(processDefinitionId);
        model.setProcessInstanceId("");
        model.setProcessSerialNumber(processSerialNumber);
        model.setTaskDefKey(taskDefKey);
        model.setTitle(draft.getTitle());
        model.setActivitiUser(orgUnitId);
        model.setItembox(ItemBoxTypeEnum.DRAFT.getValue());
        model = documentService.genDocumentModel(itemId, processDefinitionKey, processDefinitionId, taskDefKey, mobile,
            model);
        model = documentService.menuControl(model);
        return model;
    }

    @Override
    public Page<DraftEntity> pageDraftList(String itemId, String userId, int page, int rows, String title,
        boolean delFlag) {
        PageRequest pageable =
            PageRequest.of(page > 0 ? page - 1 : 0, rows, Sort.by(Sort.Direction.DESC, "urgency", "draftTime"));
        Page<DraftEntity> list;
        title = "%" + title + "%";
        if (delFlag) {
            if (StringUtil.isEmpty(itemId)) {
                list = draftEntityRepository.findByCreaterIdAndTitleLikeAndDelFlagTrue(userId, title, pageable);
            } else {
                list = draftEntityRepository.findByItemIdAndCreaterIdAndTitleLikeAndDelFlagTrue(itemId, userId, title,
                    pageable);
            }
        } else {
            if (StringUtil.isEmpty(itemId)) {
                list = draftEntityRepository.findByCreaterIdAndTitleLikeAndDelFlagFalse(userId, title, pageable);
            } else {
                list = draftEntityRepository.findByItemIdAndCreaterIdAndTitleLikeAndDelFlagFalse(itemId, userId, title,
                    pageable);
            }
        }
        return list;
    }

    @Override
    public void handelFormData(String itemId, List<Map<String, Object>> items, List<String> processSerialNumbers) {
        Map<String, Map<String, Object>> formDataResultData =
            formDataService.getDataByProcessSerialNumbers(itemId, processSerialNumbers);
        items.forEach(map -> {
            Map<String, Object> formDataMap = formDataResultData.get(map.get("processSerialNumber").toString());
            if (null != formDataMap) {
                formatFormData(formDataMap);
                map.putAll(formDataMap);
            } else {
                LOGGER.error("流程序列号{}对应的表单数据为null！", map.get("processSerialNumber"));
            }
        });

    }

    void formatFormData(Map<String, Object> map) {
        if (map.get(ItemConsts.LEAVETYPE_KEY) != null) {
            String leaveType = (String)map.get(ItemConsts.LEAVETYPE_KEY);
            ItemLeaveTypeEnum[] arr = ItemLeaveTypeEnum.values();
            for (ItemLeaveTypeEnum leaveTypeEnum : arr) {
                if (leaveType.equals(leaveTypeEnum.getValue())) {
                    map.put(ItemConsts.LEAVETYPE_KEY, leaveTypeEnum.getName());
                    break;
                }
            }
        }
    }

    @Override
    public Page<DraftEntity> pageDraftListBySystemName(String systemName, String userId, int page, int rows,
        String title, boolean delFlag) {
        PageRequest pageable =
            PageRequest.of(page > 0 ? page - 1 : 0, rows, Sort.by(Sort.Direction.DESC, "urgency", "draftTime"));
        Page<DraftEntity> list;
        title = "%" + title + "%";
        if (delFlag) {
            list = draftEntityRepository.findByTypeAndCreaterIdAndTitleLikeAndDelFlagTrue(systemName, userId, title,
                pageable);
        } else {
            list = draftEntityRepository.findByTypeAndCreaterIdAndTitleLikeAndDelFlagFalse(systemName, userId, title,
                pageable);
        }
        return list;
    }

    @Transactional
    @Override
    public void reduction(String ids) {
        if (StringUtils.isNotBlank(ids)) {
            String[] id = ids.split(",");
            for (String idTemp : id) {
                Optional<DraftEntity> draft = draftEntityRepository.findById(idTemp);
                if (draft.isPresent() && draft.get().getId() != null) {
                    draft.get().setDelFlag(false);
                    draftEntityRepository.save(draft.get());
                }
            }
        }
    }

    @Transactional
    @Override
    public void removeDraft(String ids) {
        if (StringUtils.isNotBlank(ids)) {
            String[] id = ids.split(SysVariables.COMMA);
            for (String idTemp : id) {
                Optional<DraftEntity> draft = draftEntityRepository.findById(idTemp);
                if (draft.isPresent()) {
                    draft.get().setDelFlag(true);
                    draftEntityRepository.save(draft.get());
                }
            }
        }
    }

    @Override
    @Transactional
    public void saveDraft(String itemId, String processSerialNumber, String processDefinitionKey, String number,
        String level, String title, String type) {
        if (StringUtils.isBlank(processSerialNumber)) {
            return;
        }

        DraftEntity draft = draftEntityRepository.findByProcessSerialNumber(processSerialNumber);
        String urgency = StringUtils.defaultIfBlank(level, "一般");

        if (draft != null && draft.getId() != null) {
            updateExistingDraft(draft, number, urgency, title, type);
        } else {
            draft = createNewDraft(itemId, processSerialNumber, processDefinitionKey, number, urgency, title, type);
        }

        draftEntityRepository.save(draft);
    }

    /**
     * 更新已存在的草稿
     */
    private void updateExistingDraft(DraftEntity draft, String number, String urgency, String title, String type) {
        draft.setUrgency(urgency);
        draft.setDocNumber(number);
        draft.setTitle(title);
        if (StringUtils.isNotBlank(type)) {
            draft.setType(type);
        }
        draft.setSerialNumber(1);
    }

    /**
     * 创建新的草稿
     */
    private DraftEntity createNewDraft(String itemId, String processSerialNumber, String processDefinitionKey,
        String number, String urgency, String title, String type) {
        DraftEntity draft = new DraftEntity();
        draft.setId(Y9IdGenerator.genId(IdType.SNOWFLAKE));
        draft.setProcessSerialNumber(processSerialNumber);
        draft.setItemId(itemId);
        draft.setProcessDefinitionKey(processDefinitionKey);
        draft.setCreaterId(Y9FlowableHolder.getOrgUnitId());

        OrgUnit orgUnit =
            orgUnitApi.getOrgUnitPersonOrPosition(Y9LoginUserHolder.getTenantId(), Y9FlowableHolder.getOrgUnitId())
                .getData();
        draft.setCreater(orgUnit.getName());
        draft.setDelFlag(false);
        draft.setUrgency(urgency);
        draft.setDocNumber(number);
        draft.setTitle(title);
        // 设置类型信息
        setTypeAndSystemInfo(draft, type, itemId);

        return draft;
    }

    /**
     * 设置类型和系统信息
     */
    private void setTypeAndSystemInfo(DraftEntity draft, String type, String itemId) {
        if (StringUtils.isNotBlank(type)) {
            draft.setType(type);
        }

        Item item = itemService.findById(itemId);
        if (item != null) {
            if (StringUtils.isBlank(type)) {
                draft.setType(item.getSystemName());
            }
            draft.setSystemName(item.getSysLevel());
        }
    }
}
